/*
 * PGN_Reader : A simple pgn reader for chess games.
 * Copyright (C) 2011 Laurent BERNABE
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gmail.bernabe.laurent.java_swing.pgn_reader.processing;

import java.util.ArrayList;

import com.gmail.bernabe.laurent.java_swing.pgn_reader.gui.PGNReaderFrame;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.move.BoardCell;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.move.PieceMovingDeltas;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.piece.Piece;

public class HalfMoveStartCellComputator {


	public HalfMoveStartCellComputator(HalfMoveData halfMoveData, PGNReaderFrame pgnFrame){
		this.theHalfMoveData = halfMoveData;
		this.pgnFrame = pgnFrame;
		moveEndCell = halfMoveData.getEndCell();
	}

	public BoardCell startCell(int playerTurn){
		BoardCell moveStartCell = null;
		Piece wantedPiece = new Piece(theHalfMoveData.movingPieceForce(), playerTurn);
		
		PieceMovingDeltas[] allowedMoves = theHalfMoveData.movingPieceForce().
			getAllowedMoves(playerTurn, theHalfMoveData,
					pgnFrame.getPlayingTape().getPawnStatusClone());
		
		allowedMoves = filterAllowedMovesIfForcedStartColumnOrRow(allowedMoves);
		allowedMoves = filterAllowedMovesFromUnreachablesCells(allowedMoves,wantedPiece);
		
		int allowedMoveIndex = 0;
		do {
			
			// inverting is needed as we go from the moveEndCell
			moveStartCell = moveEndCell.
					getCellMovedBy(allowedMoves[allowedMoveIndex]); 
		
			Piece startCellPiece = pgnFrame.getGraphicPanel().getPieceAt(moveStartCell);
			if (startCellPiece != null) {
				boolean startCellHasTheSoughtPiece = startCellPiece
						.equals(wantedPiece);
				if (startCellHasTheSoughtPiece)
					break;
			}
			allowedMoveIndex++;
		} while (allowedMoveIndex < allowedMoves.length);

		return moveStartCell;
	}

	private PieceMovingDeltas[] filterAllowedMovesIfForcedStartColumnOrRow(
			PieceMovingDeltas[] allowedMoves) {
		if (! theHalfMoveData.hasAForcedRowOrColumnStart() )
			return allowedMoves;
		
		ArrayList<PieceMovingDeltas> movesArrayList = 
			new ArrayList<PieceMovingDeltas>();
		
		for (PieceMovingDeltas currentMove : allowedMoves){
			BoardCell newStartCell = moveEndCell.getCellMovedBy(currentMove);
			boolean isAGoodCell = 
			(newStartCell.cellColumn == theHalfMoveData.forcedStartRowOrColumn()
					&& theHalfMoveData.isAStartColumnForced() ) ||
			(newStartCell.cellLine == theHalfMoveData.forcedStartRowOrColumn() 
					&& theHalfMoveData.isAStartLineForced() );
			if (isAGoodCell)
				movesArrayList.add(currentMove);
		}
		
		PieceMovingDeltas[] newAllowedMovesArray =
			new PieceMovingDeltas[movesArrayList.size()];
		movesArrayList.toArray(newAllowedMovesArray);
		return newAllowedMovesArray;
	}
	
	private PieceMovingDeltas[] filterAllowedMovesFromUnreachablesCells(
			PieceMovingDeltas[] allowedMoves,
			Piece wantedPiece) {
		ArrayList<PieceMovingDeltas> movesArrayList = 
			new ArrayList<PieceMovingDeltas>();
			
		int currentMoveIndex = 0;
		do {
			PieceMovingDeltas currentMove = allowedMoves[currentMoveIndex];
			BoardCell newStartCell = moveEndCell.getCellMovedBy(currentMove);
			if ( ! newStartCell.isOutOfBoard() ) {
				Piece startCellPiece = pgnFrame.getGraphicPanel().getPieceAt(newStartCell);
				boolean isTrajectoryIntercepted = wantedPiece.isALongRangedPiece() 
				&& startCellPiece != null &&  ! startCellPiece.equals(wantedPiece);
				if (isTrajectoryIntercepted) {
					currentMoveIndex = jumpIndexToNextSerieOfFourMoves(currentMoveIndex);
					continue;
				}
				else
					movesArrayList.add(currentMove);
			}
			currentMoveIndex++;
		} while(currentMoveIndex < allowedMoves.length);
		
		PieceMovingDeltas[] newAllowedMovesArray =
			new PieceMovingDeltas[movesArrayList.size()];
		movesArrayList.toArray(newAllowedMovesArray);
		return newAllowedMovesArray;
	}

	private int jumpIndexToNextSerieOfFourMoves(int allowedMoveIndex) {
		allowedMoveIndex = ((allowedMoveIndex/4) + 1)*4;
		return allowedMoveIndex;
	}
	
	private HalfMoveData theHalfMoveData;
	private PGNReaderFrame pgnFrame;
	private BoardCell moveEndCell;

}
